package flib;

import importExport.SVGText;

import java.io.File;
import java.util.Collections;
import java.util.Vector;

import processing.core.PApplet;
import processing.core.PFont;
import simpleGeom.Bounds3D;

import simpleGeom.HasPos2D;
import simpleGeom.HasPos3D;
import simpleGeom.Vec2D;
import simpleGeom.Vec3D;

public class CopyOfSplitApplet extends PApplet {
	Plan plan;
	PFont myFont;
String input;
	public void setup() {
		size(1024, 768);
		myFont = createFont("FFScala", 16f);
		textFont(myFont);
		FloorplanLoader2D loader = new FloorplanLoader2D();
		loader.loadWallTypes(new File("../flibConfig.xml"));
		loader.loadRoomTypes(new File("../flibConfig.xml"));
		plan = loader.loadFloorplanSVG(new File(input));
		findSplits();
		collectAxis();
		for (int i = 0; i < plan.rooms.size(); i++) {
			Room room = plan.rooms.get(i);
			println(room.getHEdges().size());
		}
		for (int i = 0; i < plan.nodes.size(); i++) {
			FlibHENode p = plan.nodes.get(i);
			p.setZ(0);
			NodeData nD=new NodeData();
			p.setData(nD);
		}
		
		collectSplitFaces2();
		
		
	}

	public void draw() {
		background(0);

		Bounds3D b3D = plan.getBounds3D();

		pushMatrix();
		stroke(0);
		strokeWeight(.1f);
		float scaleFactor = 20;
		scale(scaleFactor);
		translate(((-b3D.getCenterX() + width * 0.5f / scaleFactor)),
				((-b3D.getCenterY() + height * 0.5f / scaleFactor)));

		/*for (int i = 0; i < plan.rooms.size(); i++) {
			Room room = plan.rooms.get(i);
			if (room.ispublic) {
				fill(200);
			}
			fill(200);
			room.display(g);
			if (room.label != null) {
				fill(255, 0, 0);
				SVGText myText = room.label;
				this.textSize(0.3f);
				pushMatrix();
				translate(myText.x, myText.y);
				text(myText.text);
				popMatrix();
				point(myText.x, myText.y);
			}
		}
		stroke(255,255,0);
		for (int i = 0; i < plan.rooms.size(); i++) {
			Room room = plan.rooms.get(i);
			//Vec3D c=room.getGravityCenter();
			float cX1=room.getBounds2D().getCenterX();
			float cY1=room.getBounds2D().getCenterY();
			if (room.ispublic) {
				fill(200);
			}
			Vector<HEFace>nbs=room.getNbs();
			for (int j=0;j<nbs.size();j++){
				HEFace f=nbs.get(j);
				float cX=f.getBounds2D().getCenterX();
				float cY=f.getBounds2D().getCenterY();
				line(cX1,cY1,cX,cY);
			}
			
		}
		*/
		

		noStroke();
		fill(0, 255, 255);
		rectMode(CENTER);
		Vector<FlibHEdge> hEdges = plan.getAllHEdges();
		for (int i = 0; i < hEdges.size(); i++) {
			FlibHEdge hE = hEdges.get(i);

			FlibHEData heData = (FlibHEData) hE.getData();
			if (heData.nextAxisEdge == null) {
				rect(hE.getX2(), hE.getY2(), 0.2f, 0.2f);
			}
		}
		strokeCap(PROJECT);
		stroke(255);
		colorMode(HSB);
		for (int i = 0; i < splits.size(); i++) {
			Split split = splits.get(i);
			strokeWeight(i * 0.02f);
			// stroke(i*10,255,255);
			for (int j = 0; j < split.hEdges.size(); j++) {
				FlibHEdge hE = split.hEdges.get(j);
				hE.display(g);
			}

		}
		colorMode(RGB);
		Vector<Room> splitLeaves = new Vector<Room>();
		roomRoot.collectAllLeaves(splitLeaves);
		noStroke();
		stroke(255);
		strokeWeight(0.1f);
		randomSeed(1);
		noFill();
		fill(255,0,255);
		println(splitLeaves.size());
		for (int i = 0; i < splitLeaves.size(); i++) {
			Room sA = splitLeaves.get(i);
			fill(random(255),random(255),random(255));
			sA.display(g);
			
			//HasPos2D cP=sA.startP.p;
			//rect(cP.getX(),cP.getY(),0.5f,0.5f);
			stroke(random(255), random(255), 0);
			//translate(random(-0.5f, 0.5f), random(-0.5f, 0.5f));
			//sA.display(g);
		}
		
		for (int i = 0; i < plan.walls.size(); i++) {
			FlibWall wall = plan.walls.get(i);
			FlibHEdge hE = wall.hEdge;
			if (wall.type != null) {
				
				stroke(wall.type.color.getRGB());
			}
			line(hE.x1(), hE.y1(), hE.x2(), hE.y2());
			if (wall.type.label.equals("wall")) {
				noFill();
			} else {
				noFill();
			}
		}
		
		popMatrix();
	}
	SplitArea root;
	Room roomRoot;
	public void collectSplitFaces2() {
		Vector<FlibHEdge> hEdges = plan.getAllHEdges();
		Vector<Room> areas = new Vector<Room>();
		roomRoot = null;
		for (int i = 0; i < hEdges.size(); i++) {
			FlibHEdge hE = hEdges.get(i);
			if (hE.getFace() == null) {
				Vector<FlibHENode> nodes = hE.getFaceNodes();
				roomRoot = new Room();
				//roomRoot.setPts(hE.get)
				//roomRoot.setPts(nodes);
				areas.add(roomRoot);
				break;
			}
		}
		for (int i = 0; i < hEdges.size(); i++) {
			FlibHEdge hE = hEdges.get(i);
			hE.detach();
		}
		//println("size: " + root.getPts().size());
		fill(0, 255, 0);
		// area1.display(g);
		stroke(0, 255, 255);
		while (areas.size() > 0) {
			println("gen: " + areas.size());
			Vector<Room> newAreas = new Vector<Room>();
			for (int j = 0; j < areas.size(); j++) {
				Room area = areas.get(j);
				if (!area.checked) {
					for (int i = 0; i < splits.size(); i++) {
						Split split = splits.get(i);
						if (area.split!=split  && area.contains(split)) {
							//split.checked = true;
							area.checked = true;
							
							Vector<Room> splitAreas = area.split(split);
							newAreas.addAll(splitAreas);
							break;
						}
					}
				}
			}
			areas = newAreas;
		}
	}
	public void collectSplitFaces() {
		Vector<FlibHEdge> hEdges = plan.getAllHEdges();
		Vector<SplitArea> areas = new Vector<SplitArea>();
		root = null;
		for (int i = 0; i < hEdges.size(); i++) {
			FlibHEdge hE = hEdges.get(i);
			if (hE.getFace() == null) {
				Vector<FlibHENode> nodes = hE.getFaceNodes();
				root = new SplitArea();
				root.setPts(nodes);
				areas.add(root);
				break;
			}
		}
		println("size: " + root.getPts().size());
		fill(0, 255, 0);
		// area1.display(g);
		stroke(0, 255, 255);
		while (areas.size() > 0) {
			println("gen: " + areas.size());
			Vector<SplitArea> newAreas = new Vector<SplitArea>();
			for (int j = 0; j < areas.size(); j++) {
				SplitArea area = areas.get(j);
				if (!area.checked) {
					for (int i = 0; i < splits.size(); i++) {
						Split split = splits.get(i);
						if (area.split!=split  && area.contains(split)) {
							//split.checked = true;
							area.checked = true;
							
							Vector<SplitArea> splitAreas = area.split(split);
							newAreas.addAll(splitAreas);
							break;
						}
					}
				}
			}
			areas = newAreas;
		}
	}

	Vector<Split> splits;

	public void collectAxis() {
		Vector<FlibHEdge> hEdges = plan.getAllHEdges();

		splits = new Vector<Split>();

		for (int i = 0; i < hEdges.size(); i++) {
			FlibHEdge hE = hEdges.get(i);
			FlibHEData heData = (FlibHEData) hE.getData();
			if (hE.getFace() != null && hE.getSym().getFace() != null) {
				if (heData.nextAxisEdge == null && heData.split == null) {
					Split split = new Split();
					splits.add(split);
					FlibHEdge symHE = hE.getSym();
					do {
						FlibHEData symHEData = (FlibHEData) symHE.getData();
						symHEData.split = split;
						FlibHEData symHEData2 = (FlibHEData) symHE.getSym().getData();
						symHEData2.split = split;
						split.hEdges.add(symHE);
						symHE = symHEData.nextAxisEdge;
						// println("symHE: "+symHE);
					} while (symHE != null);
				}
			}
		}
		Collections.sort(splits);

	}

	public void findSplits(FlibHEdge hEdge) {

		FlibHEData heData = (FlibHEData) hEdge.getData();
		if (heData.nextAxisEdge == null) {
			FlibHEdge start = hEdge.getSym();
			FlibHEdge sym = start;
			float cAngle1 = (float) hEdge.getAngle();
			FlibHEdge nextAxis = null;
			float deltaAxis = 180;
			do {
				float deltaAngle = Vec2D.getAngleBetween(start.getDest(),
						start.getOrg(), sym.getDest());
				if (abs(deltaAngle - PI) < deltaAxis) {
					deltaAxis = abs(deltaAngle - PI);
					nextAxis = sym;
				}
				sym = sym.getNextO();
			} while (sym != hEdge.getSym());

			if (deltaAxis < 0.2f) {
				heData.nextAxisEdge = nextAxis;
				((FlibHEData) nextAxis.getSym().getData()).nextAxisEdge = hEdge
						.getSym();
			}
		}
	}

	public void findSplits() {

		for (int i = 0; i < plan.walls.size(); i++) {
			FlibWall wall = plan.walls.get(i);
			FlibHEdge hEdge = wall.hEdge;
			if (hEdge.getFace() != null && hEdge.getSym().getFace() != null) {
				findSplits(hEdge);
				findSplits(hEdge.getSym());
			}
		}

	}
}
